/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.debugger.support;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ResourceBundle;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.JComponent;
import org.openide.TopManager;
import org.openide.nodes.Node;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.text.Line;
import org.openide.cookies.LineCookie;
import org.openide.cookies.DebuggerCookie;
import org.openide.debugger.Breakpoint;
import org.openide.debugger.DebuggerNotFoundException;
import org.openide.debugger.Watch;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.Repository;
import org.openide.text.Line;
import org.openide.src.ConstructorElement;
/**
* Standart implementation of breakpoint interface.
* @see org.openide.debugger.Breakpoint
*
* @author Jan Jancura
* @version 0.23, May 26, 1998
*/
public class CoreBreakpoint extends Breakpoint implements java.io.Serializable {
/** generated Serialized Version UID */
static final long serialVersionUID = 3686204002781932191L;
/** Property name constant */
public static final String PROP_LINE_NUMBER = "lineNumber"; // NOI18N
/** Property name constant */
public static final String PROP_CLASS_NAME = "className"; // NOI18N
/** Property name constant */
public static final String PROP_METHOD_NAME = "methodName"; // NOI18N
/** Property name constant */
public static final String PROP_EVENT = "event"; // NOI18N
/** Property name constant */
public static final String PROP_ACTIONS = "actions"; // NOI18N
/** Property name constant */
public static final String PROP_HIDDEN = "hidden"; // NOI18N
/** Property name constant */
public static final String PROP_CONDITION = "condition"; // NOI18N
/** Property name constant */
// public static final String PROP_ACTION = "action"; // NOI18N
/** bundle to obtain text information from */
private static ResourceBundle bundle = org.openide.util.NbBundle.getBundle
(CoreBreakpoint.class);
// private variables .....................................................
protected transient AbstractDebugger debugger;
private boolean enabled = true;
private boolean valid = false;
private boolean hidden = false;
private String condition = new String ("");
protected transient ArrayList lines = null;
protected Event event;
private Action[] actions;
transient PropertyChangeSupport pcs;
// init ....................................................................
/**
* Non public constructor called from the AbstractDebugger only.
* User must create breakpoint from Debugger.getNewBreakpoint () method.
*/
protected CoreBreakpoint (AbstractDebugger debugger) {
this.debugger = debugger;
pcs = new PropertyChangeSupport (this);
}
/**
* Non public constructor called from the AbstractDebugger only.
* User must create breakpoint from Debugger.getNewBreakpoint () method.
*/
protected CoreBreakpoint (AbstractDebugger debugger, boolean hidden) {
this (debugger);
this.hidden = hidden;
}
protected void init () throws java.io.IOException {
try {
debugger = (AbstractDebugger) TopManager.getDefault ().getDebugger ();
} catch (DebuggerNotFoundException e) {
throw new java.io.IOException ();
}
if (condition == null) condition = "";
pcs = new PropertyChangeSupport (this);
if (enabled) setBreakpoint ();
}
private void readObject (java.io.ObjectInputStream in)
throws java.io.IOException, ClassNotFoundException {
in.defaultReadObject ();
init ();
}
// interface Breakpoint .........................................................
/** Destroys the breakpoint. Removes it from the list of all breakpoints in the system.
*/
public void remove () {
//S ystem.out.println("CoreBreakpoint.remove "); // NOI18N
clearBreakpoint ();
debugger.removeBreakpoint (this);
}
/**
* Returns the line this breakpoint is on.
*
* @return the line this breakpoint is on.
*/
public Line getLine () {
if (lines == null) return null;
return (Line) lines.get (0);
}
/**
* Returns the class name this breakpoint is in.
*
* @return the class name this breakpoint is in.
*/
public String getClassName () {
if (event instanceof ClassBreakpointEvent)
return ((ClassBreakpointEvent) event).getClassName ();
return null;
}
/**
* Getter for the method the breakpoint is assigned to.
*
* @return the method element or null
*/
public ConstructorElement getMethod () {
return null; //[PENDING]
}
/**
* Getter method for condition property.
*
* @return state of condition property.
*/
public String getCondition () {
return condition;
}
/**
* Setter method for condition property.
*
* @param state of condition property.
*/
public void setCondition (String expr) {
if (condition == expr) return;
String old = condition;
condition = expr;
firePropertyChange (PROP_CONDITION, old, expr);
}
/**
* Getter method for enabled property.
*
* @return state of enabled property.
*/
public boolean isEnabled () {
return enabled;
}
/**
* Setter method for enabled property.
*
* @param state of enabled property.
*/
public void setEnabled (boolean enabled) {
if (enabled == this.enabled) return;
boolean old = this.enabled;
this.enabled = enabled;
if (enabled) setBreakpoint ();
else clearBreakpoint ();
firePropertyChange (PROP_ENABLED, new Boolean (old), new Boolean (enabled));
}
/**
* Getter method for valid property.
*
* @return state of valid property.
*/
public boolean isValid () {
return valid;
}
/**
* Adds listener on the property changing.
*/
public synchronized void addPropertyChangeListener (PropertyChangeListener listener) {
pcs.addPropertyChangeListener (listener);
}
/**
* Removes listener on the property changing.
*/
public synchronized void removePropertyChangeListener (PropertyChangeListener listener){
pcs.removePropertyChangeListener (listener);
}
// other public methods .........................................................
/**
* Sets line on this breakpoint.
*/
public void setLine (Line line) {
clearBreakpoint ();
if (event instanceof LineBreakpointEvent) {
((LineBreakpointEvent) event).setLine (line);
} else {
initEvent (LineBreakpointEvent.class);
((LineBreakpointEvent) event).setLine (line);
}
}
/**
* Sets line number of this breakpoint.
*
* @param lineNumber line number of this breakpoint.
*/
public void setLineNumber (int lineNumber) {
clearBreakpoint ();
if (event instanceof LineBreakpointEvent) {
((LineBreakpointEvent) event).setLineNumber (lineNumber);
} else {
initEvent (LineBreakpointEvent.class);
((LineBreakpointEvent) event).setLineNumber (lineNumber);
}
}
/**
* Sets class name of this breakpoint.
*
* @param name name of class of this breakpoint.
*/
public void setClassName (String name) {
name = name.trim ();
clearBreakpoint ();
if (event instanceof ClassBreakpointEvent) {
((ClassBreakpointEvent) event).setClassName (name);
} else {
initEvent (ClassBreakpointEvent.class);
((ClassBreakpointEvent) event).setClassName (name);
}
}
/**
* Returns the method name this breakpoint is in.
*
* @return the class name this breakpoint is in.
*/
public String getMethodName () {
if (event instanceof MethodBreakpointEvent)
return ((MethodBreakpointEvent) event).getMethodName ();
return null;
}
/**
* Sets breakpoint on the method with name specified.
*
* @param name name of method to set breakpoint on.
*/
public void setMethodName (String name) {
name = name.trim ();
clearBreakpoint ();
if (event instanceof MethodBreakpointEvent) {
((MethodBreakpointEvent) event).setMethodName (name);
} else {
initEvent (MethodBreakpointEvent.class);
((MethodBreakpointEvent) event).setMethodName (name);
}
}
/**
* Returns the line number this breakpoint is on.
*
* @return the line number this breakpoint is on.
*/
public int getLineNumber () {
if (event instanceof LineBreakpointEvent)
return ((LineBreakpointEvent) event).getLineNumber ();
return -1;
}
/**
* Returns current breakpoint event for given instance of debugger (used
* in multisession debugger implementation).
*/
public Event getEvent (AbstractDebugger debugger) {
return event;
}
/**
* Sets current breakpoint event.
*/
public void setEvent (Event i) {
clearBreakpoint ();
Event old = event;
event = i.get (this);
initActions ();
setBreakpoint ();
firePropertyChange (PROP_EVENT, old, event);
}
/** Returns events available for this breakpoint.
*/
public CoreBreakpoint.Event[] getBreakpointEvents () {
return debugger.getBreakpointEvents ();
}
/**
* Returns actions availabled for this breakpoint.
*/
public CoreBreakpoint.Action[] getActions () {
return actions;
}
/**
* Returns action of given type.
*/
public CoreBreakpoint.Action getAction (Class actionType) {
int i, k = actions.length;
for (i = 0; i < k; i++)
if (actions [i].getClass ().isAssignableFrom (actionType))
return actions [i];
return null;
}
/**
* Returns actions availabled for this breakpoint.
*/
public void setActions (CoreBreakpoint.Action[] act) {
Action[] old = actions;
actions = act;
int i, k = actions.length;
for (i = 0; i < k; i ++)
actions [i] = actions [i].get (this);
firePropertyChange (PROP_ACTIONS, old, actions);
}
/**
* Returns debugger instance.
*/
/* public AbstractDebugger getDebugger () {
return debugger;
}*/
/**
* Performs given event for all actions.
*/
private void perform(Event e) {
// [PENDING] implementation of filtering here..
boolean performActions = true;
AbstractDebugger debugger = (AbstractDebugger) e.getDebugger ();
if (debugger.supportsExpressions ()) {
AbstractWatch watch = (AbstractWatch) debugger.createWatch (condition, true);
watch.refresh (e.getThread ());
String type = watch.getType();
String value = watch.getAsText();
watch.remove ();
if ((type != null) && type.equals ("boolean") && (value != null) && value.equals ("false")) // NOI18N
performActions = false;
if ((!condition.trim ().equals ("")) && ((type == null) || (!type.equals ("boolean")))) { // NOI18N
// ivalid condition, report message ...
final ResourceBundle bundle = org.openide.util.NbBundle.getBundle (CoreBreakpoint.class);
debugger.println (bundle.getString ("CTL_Incorrect_condition") + ": " + // NOI18N
bundle.getString ("CTL_breakpoint_at") + " " + e.getDisplayName () + ".", debugger.ERR_OUT); // NOI18N
}
}
if (! performActions)
((StopEvent)e).stop (false);
else { // perform actions ...
int i, k = actions.length;
for (i = 0; i < k; i ++) // stop actions will be performed in the end
if (! ((actions [i]) instanceof StopAction))
actions [i].perform (e);
for (i = 0; i < k; i ++)
if ((actions [i]) instanceof StopAction)
actions [i].perform (e);
}
}
/**
* Sets or updates breakpoint. Calls set method of currently selected event, sets
* value of valid property and marks lines in the editor.
*/
protected void setBreakpoint () {
if (!enabled) return;
boolean valid = false;
if (event != null) {
if (debugger.getState () == AbstractDebugger.DEBUGGER_NOT_RUNNING)
event.remove ();
else
valid = event.set ();
Line[] l = event.getLines ();
if (l != null)
remark (new ArrayList (Arrays.asList (l)));
else
remark (null);
}
setValid (valid);
}
/**
* Removes breakpoint from this position.
* Clears Line and breakpoint from RemoteDebugger.
*/
protected void clearBreakpoint () {
mark (false);
lines = null;
if (event != null)
event.remove ();
setValid (false);
}
public boolean isHidden () {
return hidden;
}
public void setHidden (boolean hidden) {
if (this.hidden == hidden) return;
this.hidden = hidden;
Line[] l;
if (enabled && ((l = event.getLines ()) != null))
remark (new ArrayList (Arrays.asList (l)));
else
remark (null);
firePropertyChange (PROP_HIDDEN, new Boolean (!hidden), new Boolean (hidden));
debugger.changeHidden (this);
}
// private helper methods .................................................................
/**
* Sets property valide and fires it.
*
* @param valid value of this property to be set.
*/
protected void setValid (boolean valid) {
if (valid == this.valid) return;
boolean old = this.valid;
this.valid = valid;
firePropertyChange (PROP_VALID, new Boolean (old), new Boolean (valid));
}
/**
* Marks or unmarks all important lines.
*/
protected void mark (boolean b) {
if (lines == null) return;
if (isHidden () && b) return;
int i, k = lines.size ();
for (i = 0; i < k; i++)
((Line) lines.get (i)).setBreakpoint (b);
}
/**
* Remarks lines to new positions.
*/
protected void remark (ArrayList n) {
int i, k = (n == null) ? 0 : n.size ();
if (!isHidden ())
for (i = 0; i < k; i++)
if ((lines == null) || !lines.remove (n.get (i)))
((Line) n.get (i)).setBreakpoint (true);
k = (lines == null) ? 0 : lines.size ();
for (i = 0; i < k; i++)
((Line) lines.get (i)).setBreakpoint (false);
if (isHidden ())
lines = null;
else
lines = n;
}
/**
* Creates breakpoint actions from debugger actions and event actions.
*/
protected void initActions () {
int l = (event == null) ? 0 : event.getBreakpointActions ().length;
actions = new CoreBreakpoint.Action [debugger.getBreakpointActions ().length + l];
System.arraycopy (debugger.getBreakpointActions (), 0, actions, 0, debugger.getBreakpointActions ().length);
if (event != null)
System.arraycopy (event.getBreakpointActions (), 0, actions, debugger.getBreakpointActions ().length, l);
int i, k = actions.length;
for (i = 0; i < k; i ++)
actions [i] = actions [i].get (this);
}
/**
* Initializes and sets event of given type.
*/
protected Event initEvent (Class cl) {
Event old = event;
event = getEvent (cl);
event = event.get (this);
firePropertyChange (PROP_EVENT, old, event);
initActions ();
if ((old instanceof ClassBreakpointEvent) &&
(event instanceof ClassBreakpointEvent)
) ((ClassBreakpointEvent) event).setClassName (((ClassBreakpointEvent) old).getClassName ());
return event;
}
/**
* Returns event of given type.
*/
protected Event getEvent (Class cl) {
Event[] impls = debugger.getBreakpointEvents ();
int i, k = impls.length;
for (i = 0; i < k; i++)
if (cl.isAssignableFrom (impls [i].getClass ()))
return impls [i];
return null;
}
/**
* Fires property change.
*/
protected void firePropertyChange (String s, Object o, Object n) {
pcs.firePropertyChange (s, o, n);
}
/**
* Fires property change of some event property (Needs re-setBreakpoint).
*/
protected void fireEventPropertyChange (Event e, String s, Object o, Object n) {
firePropertyChange (null, o, n);
if (enabled) setBreakpoint ();
}
/**
* Returns string representation of this class.
*/
public String toString() {
return "The Breakpoint: " + getClassName () + ((getLineNumber () < 0) ? // NOI18N
("." + getMethodName ()) : (":" + getLineNumber ())); // NOI18N
}
// innerclasses .................................................................................
/**
* Breakpoint event implementation represents type of breakpoint (like breakpoint on class,
* method, exception).
*/
public abstract static class Event implements java.io.Serializable {
static final long serialVersionUID =-4232563710736961248L;
/** Proper instance of breakpoint. */
private CoreBreakpoint breakpoint;
/** Proper instance of debugger. */
private AbstractDebugger debugger;
private void readObject (java.io.ObjectInputStream in)
throws java.io.IOException, ClassNotFoundException {
in.defaultReadObject ();
try {
debugger = (AbstractDebugger) TopManager.getDefault ().getDebugger ();
} catch (DebuggerNotFoundException e) {
throw new java.io.IOException ();
}
}
/**
* Returns a new instance of event for given breakpoint.
*/
public Event get (CoreBreakpoint breakpoint) {
Event i = getNewInstance ();
i.breakpoint = breakpoint;
i.debugger = breakpoint.debugger;
return i;
}
/**
* Returns a new instance of event for given breakpoint and debugger.
*/
public Event get (CoreBreakpoint breakpoint, AbstractDebugger debugger) {
Event i = getNewInstance ();
i.breakpoint = breakpoint;
i.debugger = debugger;
return i;
}
/**
* Returns breakpoint for this event.
*/
public CoreBreakpoint getBreakpoint () {
return breakpoint;
}
/**
* Returns debugger instance for this event.
*/
public AbstractDebugger getDebugger () {
return debugger;
}
/**
* Fires change of property.
*/
protected void firePropertyChange (String s, Object o, Object n) {
breakpoint.fireEventPropertyChange (this, s, o, n);
}
/**
* Must be called when breakpoint is reached.
*/
protected void perform () {
breakpoint.perform (this);
}
/**
* Returns actions available specially for this version of event.
*/
public CoreBreakpoint.Action[] getBreakpointActions () {
return new CoreBreakpoint.Action [0];
}
/**
* Returns new initialized instance of event.
*/
protected abstract Event getNewInstance ();
/**
* Returns specific properties of this event.
*/
public abstract Node.Property[] getProperties();
/**
* Returns name of type of this event.
*/
public abstract String getTypeName ();
/**
* Returns display name of this event.
*/
public abstract String getTypeDisplayName ();
/**
* Returns display name of this instance of event. It will be used
* as the name of the breakpoint.
*/
public abstract String getDisplayName ();
/**
* Returns name of icon.
*/
public abstract String getIconBase ();
/**
* Returns lines to highlite in the editor.
*/
public abstract Line[] getLines ();
/**
* Returns customizer visual component.
*/
public abstract JComponent getCustomizer ();
/**
* Sets breakpoint.
*/
public abstract boolean set ();
/**
* Clears breakpoint.
*/
public abstract void remove ();
/**
* Aditional ifno about debugger state when this event occures.
* If event do not produce this type of info, null is returned.
*/
public AbstractThread getThread () {
return null;
}
/**
* Aditional ifno about debugger state when this event occures.
* If event do not produce this type of info, null is returned.
*/
public CallStackFrame[] getCallStack () {
return null;
}
/**
* Aditional info about debugger state when this event occures.
* If event do not produce this type of info, null is returned.
*/
public AbstractVariable getVariable () {
return null;
}
/**
* Set valid property of this breakpoint.
*/
public void setValid (boolean valid) {
breakpoint.setValid (valid);
}
}
/**
* Breakpoint action implementation represents actions which will be performed on some
* breakpoint event (like stop debugger, show some message, show stack trace).
*/
public abstract static class Action implements java.io.Serializable {
static final long serialVersionUID = 5993327662505228239L;
/** Proper instance of debugger. */
private CoreBreakpoint breakpoint;
/**
* Returns new initialized instance of action.
*/
protected abstract Action getNewInstance ();
/**
* Returns breakpoint for this event.
*/
public CoreBreakpoint getBreakpoint () {
return breakpoint;
}
/**
* Returns debugger instance.
*/
public AbstractDebugger getDebugger () {
return breakpoint.debugger;
}
/**
* Fires change of property.
*/
protected void firePropertyChange (String s, Object o, Object n) {
breakpoint.firePropertyChange (s, o, n);
}
/**
* Returns specific properties of this event.
*/
public Node.Property[] getProperties () {
return new Node.Property [0];
}
/**
* Returns customizer visuall component or null, if Action is not
* customizable.
*/
public JComponent getCustomizer () {
return null;
}
/**
* This method is called for each action when some breakpoint event is riched.
*/
protected abstract void perform (Event e);
// helper methods .............................................................................
/**
* Returns a new instance of action for given breakpoint.
*/
Action get (CoreBreakpoint breakpoint) {
Action i = getNewInstance ();
i.breakpoint = breakpoint;
return i;
}
}
}
/*
* Log
* 3 Tuborg 1.2
*/